]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
introspect: Split out DBusSenderChecker
authorFlorian Müllner <fmuellner@gnome.org>
Wed, 16 Jun 2021 17:09:42 +0000 (19:09 +0200)
committerMarge Bot <marge-bot@gnome.org>
Fri, 3 Sep 2021 21:34:58 +0000 (21:34 +0000)
Restricting callers to a list of allowed senders is useful for
other D-Bus services as well, so split out the existing code
into a reusable class.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3943

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1970>

js/misc/introspect.js
js/misc/util.js

index 8e469fbea3c4f7bcf98f24605da94e0a439324a3..22bd8319c43b51831c863d31a9fc93c87a317d8e 100644 (file)
@@ -9,6 +9,7 @@ const APP_ALLOWLIST = [
 const INTROSPECT_DBUS_API_VERSION = 3;
 
 const { loadInterfaceXML } = imports.misc.fileUtils;
+const { DBusSenderChecker } = imports.misc.util;
 
 const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
 
@@ -43,14 +44,7 @@ var IntrospectService = class {
 
         this._syncRunningApplications();
 
-        this._allowlistMap = new Map();
-        APP_ALLOWLIST.forEach(appName => {
-            Gio.DBus.watch_name(Gio.BusType.SESSION,
-                appName,
-                Gio.BusNameWatcherFlags.NONE,
-                (conn, name, owner) => this._allowlistMap.set(name, owner),
-                (conn, name) => this._allowlistMap.delete(name));
-        });
+        this._senderChecker = new DBusSenderChecker(APP_ALLOWLIST);
 
         this._settings = St.Settings.get();
         this._settings.connect('notify::enable-animations',
@@ -67,10 +61,6 @@ var IntrospectService = class {
         return app.get_windows().some(w => w.transient_for == null);
     }
 
-    _isSenderAllowed(sender) {
-        return [...this._allowlistMap.values()].includes(sender);
-    }
-
     _getSandboxedAppId(app) {
         let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
         return ids.find(id => id != null);
@@ -127,21 +117,9 @@ var IntrospectService = class {
                 type == Meta.WindowType.UTILITY;
     }
 
-    _checkInvocation(invocation) {
-        if (global.context.unsafe_mode)
-            return;
-
-        if (this._isSenderAllowed(invocation.get_sender()))
-            return;
-
-        throw new GLib.Error(Gio.DBusError,
-            Gio.DBusError.ACCESS_DENIED,
-            'App introspection not allowed');
-    }
-
     GetRunningApplicationsAsync(params, invocation) {
         try {
-            this._checkInvocation(invocation);
+            this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
@@ -156,7 +134,7 @@ var IntrospectService = class {
         let windowsList = {};
 
         try {
-            this._checkInvocation(invocation);
+            this._senderChecker.checkInvocation(invocation);
         } catch (e) {
             invocation.return_gerror(e);
             return;
index 8139d3f47cfcce2200f72731d5768210dd96ff96..bd5718472835672bc48b8761d9b401c94f41bb70 100644 (file)
@@ -1,7 +1,8 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 /* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
             formatTime, formatTimeSpan, createTimeLabel, insertSorted,
-            ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare */
+            ensureActorVisibleInScrollView, wiggle, lerp, GNOMEversionCompare,
+            DBusSenderChecker */
 
 const { Clutter, Gio, GLib, Shell, St, GnomeDesktop } = imports.gi;
 const Gettext = imports.gettext;
@@ -477,3 +478,57 @@ function GNOMEversionCompare(version1, version2) {
 
     return 0;
 }
+
+var DBusSenderChecker = class {
+    /**
+     * @param {string[]} allowList - list of allowed well-known names
+     */
+    constructor(allowList) {
+        this._allowlistMap = new Map();
+
+        this._watchList = allowList.map(name => {
+            return Gio.DBus.watch_name(Gio.BusType.SESSION,
+                name,
+                Gio.BusNameWatcherFlags.NONE,
+                (conn_, name_, owner) => this._allowlistMap.set(name, owner),
+                () => this._allowlistMap.delete(name));
+        });
+    }
+
+    /**
+     * @param {string} sender - the bus name that invoked the checked method
+     * @returns {bool}
+     */
+    _isSenderAllowed(sender) {
+        return [...this._allowlistMap.values()].includes(sender);
+    }
+
+    /**
+     * Check whether the bus name that invoked @invocation maps
+     * to an entry in the allow list.
+     *
+     * @throws
+     * @param {Gio.DBusMethodInvocation} invocation - the invocation
+     * @returns {void}
+     */
+    checkInvocation(invocation) {
+        if (global.context.unsafe_mode)
+            return;
+
+        if (this._isSenderAllowed(invocation.get_sender()))
+            return;
+
+        throw new GLib.Error(Gio.DBusError,
+            Gio.DBusError.ACCESS_DENIED,
+            '%s is not allowed'.format(invocation.get_method_name()));
+    }
+
+    /**
+     * @returns {void}
+     */
+    destroy() {
+        for (const id in this._watchList)
+            Gio.DBus.unwatch_name(id);
+        this._watchList = [];
+    }
+};